#ifndef Camera_h__
#define Camera_h__

#include <cassert>

// GLM.
#include "glm.hpp"

namespace le
{
	class Camera
	{
		enum ECameraBits
		{
			eCameraBits_UpdateMatrices = 0
		};

	public:
		Camera();
		virtual ~Camera();

		void SetPosition(const glm::vec3& position) { m_Position = position; UpdateViewMatrix(); }
		const glm::vec3& GetPosition() const { return m_Position; }

		void SetRight(const glm::vec3& right) { m_Right = right; UpdateViewMatrix(); }
		const glm::vec3& GetRight() const { return m_Right; }

		void SetLookat(const glm::vec3& lookat){ m_Lookat = lookat; UpdateViewMatrix(); }
		const glm::vec3& GetLookat() const { return m_Lookat;}

		void SetUp(const glm::vec3& up) {m_Up = up; UpdateViewMatrix(); }
		const glm::vec3& GetUp() const {return m_Up;}

		void SetFOV(float fov) { m_FOV = fov; }
		float GetFOV() const {return m_FOV; }

		void SetAspectRatio(float aspectRatio) { m_AspectRatio = aspectRatio;}
		float GetAspectRatio() const {return m_AspectRatio;}

		const glm::mat4& GetViewMatrix() const {return m_ViewMatrix;}
		const glm::mat4& GetProjectionMatrix() const;

		void SetNearPlane(float near);
		float GetNearPlane() const {return m_NearPlane;}

		void SetFarPlane(float far);
		float GetFarPlane() const {return m_FarPlane;}

	private:
		void UpdateViewMatrix();
		void UpdateProjectionMatrix();

	private:
		glm::vec3 m_Position;
		glm::vec3 m_Right;
		glm::vec3 m_Lookat;
		glm::vec3 m_Up;

		glm::mat4 m_ViewMatrix;
		glm::mat4 m_ProjectionMatrix;

		float m_FOV;
		float m_NearPlane;
		float m_FarPlane;
		float m_AspectRatio;
	};
}

#endif // Camera_h__